<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<script>
  /**
 * 手写深拷贝
 */

const obj1 = {
    age: 20,
    name: 'xxx',
    address: {
        city: 'beijing'
    },
    arr: ['a', 'b', 'c']
}

const obj2 = deepClone(obj1);
obj2.address.city = 'shanghai';
obj2.arr[0] = 'a1';
console.log(obj1.address.city);
console.log(obj2.address.city);
console.log(obj1.arr[0]);
console.log(obj2.arr[0]);

/**
 * 深拷贝
 * @param {Object} obj 要拷贝的对象
 * 1. typeof 能识别所有的值类型和函数, 也能判断是否是引用类型(不可细分是object, array, 还是 null)
 * 2. for in 循环, 并排除原型上的属性
 * 4. 递归调用
 * 4. 如果是值类型或者 null 直接返回
 * 5. 如果是引用类型, 继续递归
 */
function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj == null) {
        // obj 是 null ，或者不是对象和数组，直接返回
        return obj;
    }

    // 初始化返回结果
    let result;
    if (obj instanceof Array) {
        result = [];
    } else {
        result = {};
    }

    // 无论对象还是数组都能用 for in 遍历
    for (let key in obj) {
        // 保证 key 不是原型的属性
        if (obj.hasOwnProperty(key)) {
            // 递归调用！！！
            result[key] = deepClone(obj[key]);
        }
    }

    // 返回结果
    return result;
}

</script>
</body>
</html>